#include "../lib_include/TcpServer.h"
#include "../lib_include/Logger.h"
#include "../lib_include/Acceptor.h"
#include "../lib_include/EventLoop.h"
#include "../lib_include/EventLoopThreadPool.h"
#include "../lib_include/SocketsOps.h"

#include <stdio.h>

using namespace netlib;
using namespace netlib::net;

TcpServer::TcpServer(EventLoop* loop,
                     const InetAddress& listenAddr,
                     const string& nameArg,
                     Option option)
  : loop_(CHECK_NOTNULL(loop)), // CHECK_NOTNULL检查loop是否为空指针
    ipPort_(listenAddr.toIpPort()),
    name_(nameArg),
    acceptor_(new Acceptor(loop, listenAddr, option == kReusePort)),
    threadPool_(new EventLoopThreadPool(loop, name_)),
    connectionCallback_(defaultConnectionCallback),
    messageCallback_(defaultMessageCallback),
    nextConnId_(1)
{
    acceptor_->setNewConnectionCallback( // 设置监听套接字有新连接建立的时候启动的回调函数
        std::bind(&TcpServer::newConnection, this, _1, _2));
}

TcpServer::~TcpServer()
{
    loop_->assertInLoopThread();
    LOG_TRACE << "TcpServer::~TcpServer [" << name_ << "] destructing";

    for (auto& item : connections_)
    {
        TcpConnectionPtr conn(item.second);
        item.second.reset();
        conn->getLoop()->runInLoop(
        std::bind(&TcpConnection::connectDestroyed, conn));
    }
}

void TcpServer::setThreadNum(int numThreads) // 设置线程池中线程的个数
{
    assert(0 <= numThreads);
    threadPool_->setThreadNum(numThreads);
}

void TcpServer::start() // 启动服务
{
    if (started_.getAndSet(1) == 0)
    {
        threadPool_->start(threadInitCallback_); // 启动IO线程池

        assert(!acceptor_->listening()); // 断言此时未启动监听
        loop_->runInLoop(std::bind(&Acceptor::listen, get_pointer(acceptor_)));
    }
}

// 新连接建立的回调函数
void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)
{
    loop_->assertInLoopThread();
    EventLoop* ioLoop = threadPool_->getNextLoop(); // 轮叫的方式获得一个IO线程来管理连接
    char buf[64];
    snprintf(buf, sizeof buf, "-%s#%d", ipPort_.c_str(), nextConnId_);
    ++nextConnId_;
    string connName = name_ + buf;

    LOG_INFO << "TcpServer::newConnection [" << name_
            << "] - new connection [" << connName
            << "] from " << peerAddr.toIpPort();
    InetAddress localAddr(sockets::getLocalAddr(sockfd)); // 获取本地协议族地址
    TcpConnectionPtr conn(new TcpConnection(ioLoop,
                                            connName,
                                            sockfd,
                                            localAddr,
                                            peerAddr));
    connections_[connName] = conn; // 将新连接插入到连接列表
    conn->setConnectionCallback(connectionCallback_);
    conn->setMessageCallback(messageCallback_);
    conn->setWriteCompleteCallback(writeCompleteCallback_);
    conn->setCloseCallback(std::bind(&TcpServer::removeConnection, this, _1));

    // 将新连接插入到事件表中进行关注
    ioLoop->runInLoop(std::bind(&TcpConnection::connectEstablished, conn));
}

// 从列表中删除连接，removeConnectionInLoop的封装
void TcpServer::removeConnection(const TcpConnectionPtr& conn)
{ loop_->runInLoop(std::bind(&TcpServer::removeConnectionInLoop, this, conn)); }

// 从列表中删除连接
void TcpServer::removeConnectionInLoop(const TcpConnectionPtr& conn)
{
    loop_->assertInLoopThread();
    LOG_INFO << "TcpServer::removeConnectionInLoop [" << name_
            << "] - connection " << conn->name();
    size_t n = connections_.erase(conn->name()); // 在连接列表中删除连接
    (void)n;
    assert(n == 1);
    EventLoop* ioLoop = conn->getLoop();

    // 传入bind()中，shared_ptr引用计数加一，添加到IO线程的附加任务列表，等待异步执行
    // 传入的conn通过复制拷贝构造，计数加一保证计数不为0，等connectDestroyed执行完
    // 所有的与连接相关的函数已经处理完，connectDestroyed执行完，conn销毁，计数为0
    // TcpConnection自动销毁
    ioLoop->queueInLoop(std::bind(&TcpConnection::connectDestroyed, conn));
}

